package com.kinyx.framework.file;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

import com.kinyx.framework.Configs;
import com.kinyx.framework.annotation.assist.CanNotNull;
import com.kinyx.framework.annotation.assist.CanNull;
import com.kinyx.framework.annotation.assist.Throws;
import com.kinyx.framework.exception.KRuntimeException;

import lombok.AccessLevel;
import lombok.NoArgsConstructor;

/**
 * 文件写入工具类
 */
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class KFileWriter {

	/**
	 * 写文件
	 * @param fileName 文件名（全路径）
	 * @param charset 字符集
	 * @param content 文件内容
	 */
	@Throws(at = "KFileUtils.checkDirectory(File, boolean)", value = "ErrorCode0.IsNotADirectory", when = "!File.isDirectory()")
	@Throws(at = "KFileUtils.createNewFile(String)", value = "IOException", when = "File.createNewFile()")
	@Throws(at = "KFileWriter.write(String, String, String)", value = "UnsupportedEncodingException", when = "String.getBytes(String)")
	@Throws(at = "KFileWriter.write(String, String, String)", value = "FileNotFoundException", when = "new FileOutputStream(File)")
	@Throws(at = "KFileWriter.write(String, String, String)", value = "IOException", when = "FileChannel.write(ByteBuffer)")
	public static void write(@CanNotNull final String fileName, @CanNull(defaultValue = "Configs.default_KFileWriter_charset") final String charset, @CanNotNull final String content) {
		if (charset == null) { write(fileName, Configs.default_KFileWriter_charset, content); return; }
		byte[] bytes;
		try {
			bytes = content.getBytes(charset);
		} catch (final UnsupportedEncodingException e) {
			throw new KRuntimeException(e);
		}

		final File file = KFileUtils.createNewFile(fileName);

		FileOutputStream fos = null;
		try {
			fos = new FileOutputStream(file);
		} catch (final FileNotFoundException e) {
			throw new KRuntimeException(e);
		}

		final ByteBuffer bb = ByteBuffer.allocate(bytes.length);
		bb.put(bytes);
		bb.flip();

		FileChannel channel = null;
		channel = fos.getChannel();
		try {
			channel.write(bb);
		} catch (final IOException e) {
			throw new KRuntimeException(e);
		} finally {
			if (channel != null) {
				try {
					channel.close();
				} catch (final IOException e) {
					channel = null;
				}
			}
			if (fos != null) {
				try {
					fos.close();
				} catch (final IOException e) {
					fos = null;
				}
			}
		}
	}

}
